Gemini Developer APIを使ったDiscord BOT
#Gemini #API #Discord
参考:
Gemini Developer API
https://ai.google.dev/gemini-api/docs?hl=ja
Discord Botアカウントの作成
---
作成例
GeminiとおしゃべりができるDiscordBOTです。
Geminiに投げてコメント足してもらいましたhill_san.icon
ソースコード
code:discord_bot.py
import re
import discord
import google.generativeai as genai
# --- 定数定義 ---
DISCORD_TOKEN = "bbbbbbbbbbbbbbbbbbbbbbbb"
GOOGLE_API_KEY = "aaaaaaaaaaaaaaaaaaaaaaa"
MAX_MESSAGE_LENGTH = 1750 # Discordのメッセージ最大文字数(約2000文字)を考慮
# --- ヘルパー関数 ---
def to_markdown(text):
"""
テキストをDiscordの引用ブロック形式に変換します。
箇条書きのマークアップも調整します。
"""
lines = text.split('\n')
markdown_lines = []
for line in lines:
# • を Discord のリストマークアップに変換
line = line.replace('•', ' *')
markdown_lines.append('> ' + line) # 各行を引用ブロックにする
return '\n'.join(markdown_lines)
def count_unmatched_quotes(text, quote_type):
"""
指定された引用符(バッククォート)が、バッククォートで囲まれていないものをカウントします。
これにより、コードブロック内の引用符が誤ってカウントされるのを防ぎます。
"""
# 正規表現: (?<!) は後読みアサーションで、 の直後ではないことを示す
# (?!) は先読みアサーションで、 の直前ではないことを示す
return len(re.findall(rf"(?<!){quote_type}(?!)", text))
def add_quotes_if_needed(text, quote_type, added_end_quote):
"""
長文メッセージを分割する際に、引用符(例: や )の開始・終了が一致するように調整します。
"""
# 引用符の数が奇数の場合(閉じられていない引用符がある)
if count_unmatched_quotes(text, quote_type) % 2:
if added_end_quote:
# 前のチャンクで閉じ引用符が追加された場合、現在のチャンクの冒頭に開始引用符を追加
return quote_type + text, False
else:
# 現在のチャンクの末尾に閉じ引用符を追加し、フラグを立てる
return text + quote_type, True
return text, added_end_quote # 引用符の数が偶数ならそのまま返す
# --- DiscordクライアントとGeminiモデルの初期化 ---
intents = discord.Intents.default()
intents.message_content = True # メッセージの内容を読み取るためのインテントを有効化
client = discord.Client(intents=intents)
genai.configure(api_key=GOOGLE_API_KEY)
model = genai.GenerativeModel("models/gemini-2.0-flash")
# --- Discordイベントハンドラ ---
@client.event
async def on_ready():
"""
ボットがDiscordに接続し、準備が完了したときに実行されます。
"""
print(f'{client.user}が起動しました')
@client.event
async def on_message(message):
if not message or message.author == client.user:
return
# 動作確認コマンド
if message.content == 'おはよう!':
await message.channel.send('おはよう!')
return
try:
response = model.generate_content(message.content)
if not response or not response.text:
await message.channel.send('geminiは忙しいようです...')
return
added_end_single_quote = False # 単一のバッククォートの閉じ記号が追加されたか
added_end_triple_quote = False # トリプルバッククォートの閉じ記号が追加されたか
# 生成されたテキストをDiscordのメッセージ制限に合わせて分割し、送信
for i in range(0, len(response.text), MAX_MESSAGE_LENGTH):
chunk = response.texti:i + MAX_MESSAGE_LENGTH
# 単一バッククォートの整合性を調整
chunk, added_end_single_quote = add_quotes_if_needed(chunk, "`", added_end_single_quote)
# トリプルバッククォートの整合性を調整
chunk, added_end_triple_quote = add_quotes_if_needed(chunk, "`", added_end_triple_quote)
await message.channel.send(to_markdown(chunk))
except Exception as e:
# エラーが発生した場合
await message.channel.send(f'エラーが発生しました: {str(e)}')
# --- ボットの実行 ---
client.run(DISCORD_TOKEN)
クォート調整とかいう謎処理なら手書きしたほうが早いねhill_san.icon
テンプレ的な部分はGeminiさんに書いてもらいました